﻿Imports System
Imports System.Globalization
Imports System.Reflection

Namespace System.Workflow.Activities.Rules
    Friend Class ExtensionMethodInfo
        Inherits MethodInfo
        ' Methods
        Public Sub New(ByVal method As MethodInfo, ByVal actualParameters As ParameterInfo())
            Me.actualMethod = method
            Me.actualParameterLength = actualParameters.Length
            If (Me.actualParameterLength < 2) Then
                Me.expectedParameters = New ParameterInfo(0  - 1) {}
            Else
                Me.expectedParameters = New ParameterInfo((Me.actualParameterLength - 1)  - 1) {}
                Array.Copy(actualParameters, 1, Me.expectedParameters, 0, (Me.actualParameterLength - 1))
                Dim info As ParameterInfo
                For Each info In Me.expectedParameters
                    If info.ParameterType.IsByRef Then
                        Me.hasOutOrRefParameters = True
                    End If
                Next
            End If
            Me.assumedDeclaringType = actualParameters(0).ParameterType
        End Sub

        Public Overrides Function GetBaseDefinition() As MethodInfo
            Return Me.actualMethod.GetBaseDefinition
        End Function

        Public Overrides Function GetCustomAttributes(ByVal inherit As Boolean) As Object()
            Return Me.actualMethod.GetCustomAttributes(inherit)
        End Function

        Public Overrides Function GetCustomAttributes(ByVal attributeType As Type, ByVal inherit As Boolean) As Object()
            Return Me.actualMethod.GetCustomAttributes(attributeType, inherit)
        End Function

        Public Overrides Function GetMethodImplementationFlags() As MethodImplAttributes
            Return Me.actualMethod.GetMethodImplementationFlags
        End Function

        Public Overrides Function GetParameters() As ParameterInfo()
            Return Me.expectedParameters
        End Function

        Public Overrides Function Invoke(ByVal obj As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal parameters As Object(), ByVal culture As CultureInfo) As Object
            Dim destinationArray As Object() = New Object(Me.actualParameterLength  - 1) {}
            If (Me.actualParameterLength > 1) Then
                Array.Copy(parameters, 0, destinationArray, 1, (Me.actualParameterLength - 1))
            End If
            If (obj Is Nothing) Then
                destinationArray(0) = Nothing
            Else
                destinationArray(0) = Executor.AdjustType(obj.GetType, obj, Me.assumedDeclaringType)
            End If
            Dim obj2 As Object = Me.actualMethod.Invoke(Nothing, invokeAttr, binder, destinationArray, culture)
            If Me.hasOutOrRefParameters Then
                Array.Copy(destinationArray, 1, parameters, 0, (Me.actualParameterLength - 1))
            End If
            Return obj2
        End Function

        Public Overrides Function IsDefined(ByVal attributeType As Type, ByVal inherit As Boolean) As Boolean
            Return Me.actualMethod.IsDefined(attributeType, inherit)
        End Function


        ' Properties
        Public ReadOnly Property AssumedDeclaringType As Type
            Get
                Return Me.assumedDeclaringType
            End Get
        End Property

        Public Overrides ReadOnly Property Attributes As MethodAttributes
            Get
                Return (Me.actualMethod.Attributes And Not MethodAttributes.Static)
            End Get
        End Property

        Public Overrides ReadOnly Property DeclaringType As Type
            Get
                Return Me.actualMethod.DeclaringType
            End Get
        End Property

        Public Overrides ReadOnly Property MethodHandle As RuntimeMethodHandle
            Get
                Return Me.actualMethod.MethodHandle
            End Get
        End Property

        Public Overrides ReadOnly Property Name As String
            Get
                Return Me.actualMethod.Name
            End Get
        End Property

        Public Overrides ReadOnly Property ReflectedType As Type
            Get
                Return Me.actualMethod.ReflectedType
            End Get
        End Property

        Public Overrides ReadOnly Property ReturnType As Type
            Get
                Return Me.actualMethod.ReturnType
            End Get
        End Property

        Public Overrides ReadOnly Property ReturnTypeCustomAttributes As ICustomAttributeProvider
            Get
                Return Me.actualMethod.ReturnTypeCustomAttributes
            End Get
        End Property


        ' Fields
        Private actualMethod As MethodInfo
        Private actualParameterLength As Integer
        Private assumedDeclaringType As Type
        Private expectedParameters As ParameterInfo()
        Private hasOutOrRefParameters As Boolean
    End Class
End Namespace

